package com.bjpowernode.pay.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.bjpowernode.common.client.RedisClient;
import com.bjpowernode.common.consts.AppConst;
import com.bjpowernode.common.consts.Keys;
import com.bjpowernode.common.enums.Code;
import com.bjpowernode.common.pay.KQHttpUtil;
import com.bjpowernode.common.pay.PayUtil;
import com.bjpowernode.common.pay.Pkipair;
import com.bjpowernode.db.domain.AccountDetail;
import com.bjpowernode.db.domain.RechargeRecord;
import com.bjpowernode.db.domain.User;
import com.bjpowernode.db.mapper.AccountDetailMapper;
import com.bjpowernode.db.mapper.FinanceAccountMapper;
import com.bjpowernode.db.mapper.RechargeRecordMapper;
import com.bjpowernode.db.mapper.UserMapper;
import com.bjpowernode.mvc.model.dto.user.TokenUserDTO;
import com.bjpowernode.pay.model.dto.KuaiQianFormDTO;
import com.bjpowernode.pay.service.PayService;
import jakarta.annotation.Resource;
import org.apache.ibatis.annotations.Update;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


@Service
public class PayServiceImpl implements PayService {

    @Resource
    private RedisClient redisClient;
    @Resource
    private UserMapper userMapper;
    @Resource
    private RechargeRecordMapper rechargeRecordMapper;
    @Resource
    private FinanceAccountMapper accountMapper;
    @Resource
    private AccountDetailMapper accountDetailMapper;

    @Override
    public boolean checkToken(Integer userId, String token) {

        //检查token与uid是否正确
        boolean checkTokenUid = false;
        //验证一下redis,是否存在
        if (StrUtil.isNotBlank(token)) {
            String key = Keys.TOKEN_ACCESS + token.toUpperCase();
            //如果token存在
            boolean exists = redisClient.hasKey(key);
            if (exists) {
                if (String.valueOf("userId").equals(redisClient.getHashField(key, "id"))) {
                    checkTokenUid = true;
                }
            }
        }
        return checkTokenUid;
    }


    //快钱支付,创建网银支付接口需要的参数
    @Override
    public KuaiQianFormDTO createApiResuestData(Integer uid, String token, BigDecimal money) {

        User user = userMapper.selectById(uid);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        String phone = user.getPhone();

        //订单号,在商家需要唯一,我们的规则是时间戳+redis的incr的自增值
        String rechargeNo = "";
        Long seq = redisClient.incr(Keys.PAY_ORDER_SEQ);
        if (seq == null) {
            throw new RuntimeException("生成订单号的seq错误");
        }

        //时间戳
        rechargeNo = "KQ" + DateUtil.format(new Date(), "yyyyMMddHHmmssSSS") + seq;

        KuaiQianFormDTO formDTO = new KuaiQianFormDTO(uid, phone, token, rechargeNo, money);
        return formDTO;
    }


    //保存充值记录.
    @Override
    public int saveRecharge(Integer uid, String orderId, BigDecimal money) {
        RechargeRecord record = new RechargeRecord();
        record.setUid(uid);
        record.setRechargeNo(orderId);
        record.setRechargeStatus(AppConst.STATUS_RECHARGE_BEGIN);
        record.setRechargeMoney(money);
        record.setRechargeTime(new Date());
        record.setRechargeDesc("快钱充值.");
        record.setChannel("kuaiQian");

        return rechargeRecordMapper.insert(record);

    }


    //将order存到redis里(快钱充值.订单号)
    @Override
    public boolean saveOrderRedis(String orderId) {

        //使用ZSet类型,value :orderId  score:订单的生成时间
        return redisClient.addZSet(Keys.PAY_ORDER_ID, orderId, new Date().getTime());

    }


    //实现异步方法.
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String handLeKuaiQianNotify(String orderId, String payAmount, String payResult) {

        //查询订单是否存在,上锁
        RechargeRecord record = rechargeRecordMapper.selectByOrderIdForUpde(orderId);
        if (record == null) {
            return Code.PAY_ORDER_NO_EXISTS.name();
        }
        //判断订单状态.
        if (AppConst.STATUS_RECHARGE_BEGIN !=record.getRechargeStatus()){
           return Code.PAY_ORDER_HAS_DD.name();
        }


        //判断订金金额,注意统一单位.

       String fen= record.getRechargeMoney().multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();

        if (!fen.equals(payAmount)){
            return Code.PAY_ORDER_MONEY_DIFF.name();
        }


        //判断支付结果.
        RechargeRecord update=new RechargeRecord();
        int row =0;
        if ("10".equals(payResult)){
            //更新账号的余额
           row= accountMapper.addAvaiableMoneyByRecharge(record.getUid(),record.getRechargeMoney());

           if (row<1){
               throw new RuntimeException("充值,更新账号的余额失败");
           }

            AccountDetail detail=new AccountDetail();
            detail.setUid(record.getUid());
            detail.setAction(AppConst.ADD);
            detail.setActionTime(new Date());
            detail.setMemo("充值:"+record.getRechargeMoney());

            accountDetailMapper.insert(detail);

            //更新充值记录的状态成功
            update.setId(record.getId());
            update.setRechargeStatus(AppConst.STATUS_RECHARGE_SUCC);
            row= rechargeRecordMapper.updateById(update);
            if (row<1){
                throw new RuntimeException("充值,更新充值记录状态为1,失败");
            }

        }else {
            //充值失败.
            update.setId(record.getId());
            update.setRechargeStatus(AppConst.STATUS_RECHARGE_FAIT);
           row= rechargeRecordMapper.updateById(update);

           if (row<1){
               throw new RuntimeException("充值,更新充值记录状态为2,失败");
           }


        }
        return Code.SUCC.name();
    }






    //删除redis已经处理过的订单号
    @Override
    public void removeOrderIdRedis(String orderId) {
        redisClient.deleteValueZSet(Keys.PAY_ORDER_ID,orderId);
    }




    //从redis中获取登录的信息
    @Override
    public Map<String, String> getLoginTokenInfoFromRedis(String token) {
        String key=Keys.TOKEN_ACCESS + token.toUpperCase();
      Map<String,String> data= redisClient.getHashAllFiel(key);
        return data;
    }






    //从redis获取订单号
    @Override
    public  Set<ZSetOperations.TypedTuple<String>> getOrderIdFromRedis() {
        Set<ZSetOperations.TypedTuple<String>> typeTuples = redisClient.rangeWithScore(Keys.PAY_ORDER_ID, 0, -1);

        return typeTuples;
    }





    //调用快钱的查询接口
    @Override
    public String executeQueryOrder(String queryOrderId) {

        Map<String, Object> request = new HashMap<String, Object>();
        //固定值：1代表UTF-8;
        String inputCharset = "1";
        //固定值：v2.0 必填
        String version = "v2.0";
        //1代表Md5，2 代表PKI加密方式  必填
        String signType = "2";
        //人民币账号 membcode+01  必填
        String merchantAcctId = "1001214035601";
        //固定值：0 按商户订单号单笔查询，1 按交易结束时间批量查询必填
        String queryType = "0";
        //固定值：1	代表简单查询 必填
        String queryMode = "1";
        String startTime = "";
        String endTime = "";
        String requestPage = "";
        String orderId = queryOrderId;
        String key = "27YKWKBKHT2IZSQ4";

        request.put("inputCharset", inputCharset);
        request.put("version", version);
        request.put("signType", signType);
        request.put("merchantAcctId", merchantAcctId);
        request.put("queryType", queryType);
        request.put("queryMode", queryMode);
        request.put("startTime", startTime);
        request.put("endTime", endTime);
        request.put("requestPage", requestPage);
        request.put("orderId", orderId);

        String message="";
        message = PayUtil.appendParam(message,"inputCharset",inputCharset);
        message = PayUtil.appendParam(message,"version",version);
        message = PayUtil.appendParam(message,"signType",signType);
        message = PayUtil.appendParam(message,"merchantAcctId",merchantAcctId);
        message = PayUtil.appendParam(message,"queryType",queryType);
        message = PayUtil.appendParam(message,"queryMode",queryMode);
        message = PayUtil.appendParam(message,"startTime",startTime);
        message = PayUtil.appendParam(message,"endTime",endTime);
        message = PayUtil.appendParam(message,"requestPage",requestPage);
        message = PayUtil.appendParam(message,"orderId",orderId);
        message = PayUtil.appendParam(message,"key",key);

        Pkipair pki = new Pkipair();
        String sign = pki.signMsg(message);
        //签名数据也是参数
        request.put("signMsg", sign);

        //sandbox提交地址
        String reqUrl = "https://sandbox.99bill.com/gatewayapi/gatewayOrderQuery.do";
        String response = "";
        try {
            response = KQHttpUtil.doPostJsonRequestByHttps(JSONUtil.toJsonStr(request), reqUrl, 3000, 8000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response;
    }
}
